<?php
//tbf 数据库 TODO 表名和字段名正确转义
//本类不知道任何和字段相关的信息
class TbfDatabase {
    /** @var \PDO */
    private static $pdo = null;

    /** @return \PDO */
    static function getPdo(){
        if (self::$pdo!=null){
            return self::$pdo;
        }
        self::$pdo = new PDO(sprintf('mysql:host=%s;port=%d;dbname=%s;charset=utf8',
            TbfConfig::$DbHost,
            TbfConfig::$DbPort,
            TbfConfig::$DbDatabase),
            TbfConfig::$DbUsername,
            TbfConfig::$DbPassword
        );
        self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return self::$pdo;
    }
    //sql查询,会返回[]map[string]string
    static function query($sql,$data=array()){
        if (empty($data)){
            $stat = self::getPdo()->query($sql);
        }else{
            $stat = self::getPdo()->prepare($sql);
            $stat->execute($data);
        }
        return $stat->fetchAll(\PDO::FETCH_ASSOC);
    }

    //sql执行,无返回值
    static function execute($sql,$data=array()){
        if (empty($data)){
            self::getPdo()->query($sql);
        }else{
            $stat = self::getPdo()->prepare($sql);
            $stat->execute($data);
        }
        return;
    }

    //开始数据库事务,脚本退出时,会自动rollback.
    static function beginTransaction(){
        self::getPdo()->beginTransaction();
    }
    static function commit(){
        self::getPdo()->commit();
    }
    static function lastInsertId(){
        return self::getPdo()->lastInsertId();
    }

    //单条数据插入,传入表名,和本条数据格式map[string]string
    //无返回值
    static function insert($table,$row){
        if (empty($row)){
            throw new Exception('[TbfDatabase.insert] empty($data)');
        }
        $fielddata = array_keys($row);
        $valuedata = array_values($row);
        $fieldStr = '`'.implode ('`,`', $fielddata).'`';
        $valueStr = str_repeat('?,',count($row)-1).'?';
        //sql例子 INSERT INTO AdminUser (username,password) VALUES (?,?);
        $sql = sprintf('INSERT INTO `%s` (%s) VALUES (%s)',$table,$fieldStr,$valueStr);
        self::execute($sql,$valuedata);
    }

    //数据更新,传入表名,需要更新的数据,使用数据里面的'id'字段作为查询条件
    //无返回值
    static function updateById($table,$row){
        if (empty($row['id'])){
            throw new Exception('[TbfDatabase.update] empty($row[id])');
        }
        if (count($row)<=1){
            throw new Exception('[TbfDatabase.update] count($row)<=1');
        }
        $id = $row['id'];
        $updateValues = array();
        $updateArr = array();
        foreach($row as $key=>$value){
            if ($key=='id'){
                continue;
            }
            $updateArr[]='`'.$key.'`=?';
            $updateValues[] = $value;
        }
        $updateValues[] = $id;
        $updateStr = implode(',',$updateArr);
        //sql例子 UPDATE AdminUser SET username=?,password=? where id = 1;
        $sql = sprintf('UPDATE `%s` SET %s where id = ?',$table,$updateStr);
        self::execute($sql,$updateValues);
    }
}
